package com.ayu.wxgzh.ayucyy.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ayu.wxgzh.ayucyy.Utils.MapUtils;
import com.ayu.wxgzh.ayucyy.entity.auth.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 徐林玉
 * @Description WeChatUserInfoService
 * @Date 2023/2/28 11:16
 * @Version 1.0
 */

@Service
@Slf4j
public class WeChatUserInfoService {


    /**
     * 微信支付小程序APP ID
     */
    @Value("${wechat-payment.wechat-mini-app.app-id:}")
    String WECHAT_MINI_APP_APP_ID;

    /**
     * 微信支付小程序APP SECRET
     */
    @Value("${wechat-payment.wechat-mini-app.app-secret:}")
    String WECHAT_MINI_APP_APP_SECRET;


    @Value("${wechat.redirecturl:}")
    private String redirectUrl;

    @Value("${wechat.openapiurl:}")
    private String openApiUrl;

    @Value("${wechat.apiurl:}")
    private String apiUrl;


    private static final String OAUTH2_AUTHORIZE = "connect/oauth2/authorize";

    private static final String OAUTH2_ACCESS_TOKEN = "sns/oauth2/access_token";

    private static final String OAUTH2_USERINFO = "sns/userinfo";

    /**
     * 获取用户授权码
     *
     * @param baseUrl
     * @param scope
     * @return
     */
    public String getAuthCode(String baseUrl, String scope) throws UnsupportedEncodingException {
        String appId = WECHAT_MINI_APP_APP_ID;
        // 设置回调地址 http://6uks3d.natappfree.cc/wechat/auth，该地址为后端地址
        String redirectUri = redirectUrl;
        // urlEncode处理
        redirectUri = URLEncoder.encode(redirectUri, "utf-8");
        // 组装url，在url中让state属性存方baseUrl的值
        String url = openApiUrl + OAUTH2_AUTHORIZE;
        // 封装url请求参数
        Oauth2AuthorizeRep rep = new Oauth2AuthorizeRep();
        rep.setAppid(appId);
        rep.setRedirect_uri(redirectUri);
        rep.setScope(scope);
        // 设置回调参数，需要进行urlEncode处理
        Map<String, String> stateMap = new HashMap<>(4);
        stateMap.put("baseUrl", baseUrl);
        stateMap.put("scope", scope);
        String stateMapStr = JSON.toJSONString(stateMap);
        stateMapStr = new String(Base64.getEncoder().encode(stateMapStr.getBytes(StandardCharsets.UTF_8)));
        rep.setState(stateMapStr);
        // 参数的顺序必须是：appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
        url = url + MapUtils.getUrlByBean(rep) + "#wechat_redirect";

        // 重定向url，微信会自动访问redirectUri，进行回调
        return url;
    }


    /**
     * 用户授权，并且返回openid返回给前端
     *
     * @param code
     * @param scope
     * @return
     */
    public Oauth2UserInfoRes getUserAuth(String code, String scope) {

        String appId = WECHAT_MINI_APP_APP_ID;
        String secret = WECHAT_MINI_APP_APP_SECRET;
        String url = apiUrl + OAUTH2_ACCESS_TOKEN;
        // 封装url请求参数
        Oauth2AccessTokenRep rep = new Oauth2AccessTokenRep();
        rep.setAppid(appId);
        rep.setSecret(secret);
        rep.setCode(code);
        url = url + MapUtils.getUrlByBean(rep);
        String str = HttpUtil.get(url);

        Oauth2AccessTokenRes res = JSONObject.parseObject(str, Oauth2AccessTokenRes.class);

        log.info("Oauth2AccessTokenRes：" + JSON.toJSONString(res));

        // 获取access_token过期时间
        long expiresToken = res.getExpires_in() - 100;
        String access_token = res.getAccess_token();
        String openid = res.getOpenid();

        log.info("------ access_token：{} ------", access_token);
        log.info("------ openid：{} ------", openid);
        Oauth2UserInfoRes userInfo = new Oauth2UserInfoRes();
        // 根据openid和access_token获取用户信息，如果"snsapi_userinfo"授权方式，再调用接口获取用户信息
        if ("snsapi_userinfo".equalsIgnoreCase(scope)) {
            userInfo = getAndInsertUserInfo(openid, access_token);
        }
        return userInfo;
    }

    private Oauth2UserInfoRes getAndInsertUserInfo(String openid, String accessToken) {
        // 获取用户信息
        String url = apiUrl + OAUTH2_USERINFO;
        Oauth2UserInfoRep rep = new Oauth2UserInfoRep();
        rep.setAccess_token(accessToken);
        rep.setOpenid(openid);
        url = url + MapUtils.getUrlByBean(rep);
        String res = HttpUtil.get(url);
        Oauth2UserInfoRes userinfo = JSONObject.parseObject(res, Oauth2UserInfoRes.class);
        // 打印信息
        log.info("UserInfo：" + res);

        return userinfo;
    }

}
